package com.bml.client.secret.demo.CAS;

import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.LockSupport;

public class AtomicMarkableReferenceTest {
    public static void main(String[] args) {
        // 定义AtomicStampedReference    Pair.reference值为1, Pair.stamp为1

        AtomicMarkableReference<Integer> atomicMarkableReference = new AtomicMarkableReference<>(1, false);

        new Thread(() -> {
            boolean[] stampHolder = new boolean[1];
            int value = atomicMarkableReference.get(stampHolder);
            boolean stamp = stampHolder[0];
            System.out.println("Thread1 read value: " + value + ", stamp: " + stamp);

            // 阻塞1s
            LockSupport.parkNanos(1000000000L);
            // Thread1通过CAS修改value值为3
            if (atomicMarkableReference.compareAndSet(value, 3, stamp, true)) {
                System.out.println("Thread1 update from " + value + " to 3");
            } else {
                System.out.println("Thread1 update fail!");
            }
        }, "Thread1").start();

        new Thread(() -> {
            boolean[] stampHolder = new boolean[1];
            int value = atomicMarkableReference.get(stampHolder);
            boolean stamp = stampHolder[0];
            System.out.println("Thread2 read value: " + value + ", stamp: " + stamp);
            // Thread2通过CAS修改value值为2
            if (atomicMarkableReference.compareAndSet(value, 2, stamp, true)) {
                System.out.println("Thread2 update from " + value + " to 2");

                // do something

                value = atomicMarkableReference.get(stampHolder);
                stamp = stampHolder[0];
                System.out.println("Thread2 read value: " + value + ", stamp: " + stamp);
                // Thread2通过CAS修改value值为1
                if (atomicMarkableReference.compareAndSet(value, 1, false, false)) {
                    System.out.println("Thread2 update from " + value + " to 1");
                }
            }
        }, "Thread2").start();
    }
}